package com.metadata_system.system.service;


import com.alibaba.fastjson.JSON;
import com.metadata_system.common.db.entity.MetadataNode;
import com.metadata_system.common.db.entity.ProjectNode;
import com.metadata_system.common.db.entity.UserOperationLog;
import com.metadata_system.common.db.mapper.MetadataEdgeMapper;
import com.metadata_system.common.db.mapper.MetadataNodeMapper;
import com.metadata_system.common.db.mapper.MetadataViewMapper;
import com.metadata_system.common.db.mapper.UserMapper;
import com.metadata_system.common.dto.ApiResult;
import com.metadata_system.common.service.UserOperationLogService;
import com.metadata_system.common.utils.Base62Encoder;
import com.metadata_system.common.utils.MyUtil;
import com.metadata_system.system.request.MetadataNodeListParams;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MetadataNodeService {

    @Autowired(required = false)
    MetadataNodeMapper metadataNodeMapper;
    @Autowired(required = false)
    MetadataEdgeMapper metadataEdgeMapper;
    @Autowired(required = false)
    MetadataViewMapper metadataViewMapper;
    @Autowired(required = false)
    UserMapper userMapper;

    @Autowired
    MetadataService metadataService;
    @Autowired
    UserOperationLogService userOperationLogService;


    public ApiResult getList(MetadataNodeListParams listParams) {
        Example example = new Example(MetadataNode.class);
        Example.Criteria criteria = example.createCriteria();
        if (listParams.getMetadataId() != null) {
            criteria.andEqualTo("metadataId", listParams.getMetadataId());
        }
        if (listParams.getMetadataViewId() != null) {
            criteria.andEqualTo("metadataViewId", listParams.getMetadataViewId());
        }
        if (StringUtils.isNotBlank(listParams.getName())) {
            criteria.andLike("name", "%" + listParams.getName() + "%");
        }
        listParams.setOrder(example, Arrays.asList("metadataId", "metadataViewId", "name"));

        int total = metadataNodeMapper.selectCountByExample(example);
        List<MetadataNode> list = new ArrayList<>();
        if (total > 0) {
            list = metadataNodeMapper.selectByExample(example);
        }

        return ApiResult.successPage(list, total);
    }

    /**
     * 新增-节点
     *
     * @param metadataNodeParams 节点参数
     * @param fromNodeId         关联节点
     * @return
     */
    public ApiResult create(MetadataNode metadataNodeParams, String fromNodeId, Integer userId) {
        if (StringUtils.isNotBlank(fromNodeId)) {
            MetadataNode formMetadataNode = metadataNodeMapper.selectByPrimaryKey(Integer.parseInt(fromNodeId.substring(1)));
            if (formMetadataNode != null) {
                metadataNodeParams.setProperties(formMetadataNode.getProperties());
                metadataNodeParams.setName(formMetadataNode.getName());

                // 关联节点，没有唯一标识，生成一个
                if (StringUtils.isBlank(formMetadataNode.getUniqueKey())) {
                    String uniqueKey = Base62Encoder.generateUniqueKey();
                    this.metadataNodeMapper.updateByPrimaryKeySelective(
                            MetadataNode.builder().id(formMetadataNode.getId()).uniqueKey(uniqueKey).build()
                    );
                    formMetadataNode.setUniqueKey(uniqueKey);
                }

                metadataNodeParams.setUniqueKey(formMetadataNode.getUniqueKey());
                metadataNodeParams.setIsMain(0);
            } else {
                return ApiResult.error("关联节点不存在");
            }
        }else{
            metadataNodeParams.setIsMain(1);
        }
        if (metadataNodeParams.getMetadataId() == null) {
            return ApiResult.error("元数据ID 不能为空");
        }
        if (metadataNodeParams.getMetadataViewId() == null) {
            return ApiResult.error("元数据视图ID 不能为空");
        }
        if (StringUtils.isBlank(metadataNodeParams.getName())) {
            metadataNodeParams.setName("新节点");
        } else {
            if (metadataNodeParams.getName().length() < 2 || metadataNodeParams.getName().length() > 30) {
                return ApiResult.error("节点名称 长度必须在2-30之间");
            }
            if (StringUtils.isBlank(metadataNodeParams.getUniqueKey())) {
                long count = this.metadataNodeMapper.selectCount(MetadataNode.builder()
                        .metadataViewId(metadataNodeParams.getMetadataViewId())
                        .name(metadataNodeParams.getName())
                        .build());
                if (count > 0) {
                    return ApiResult.error("节点名称 已经被使用");
                }
            }
        }
        if (StringUtils.isBlank(metadataNodeParams.getUniqueKey())) {
            metadataNodeParams.setUniqueKey("");
        }
        if (StringUtils.isBlank(metadataNodeParams.getPosition())) {
            return ApiResult.error("坐标格式错误");
        }
        if (StringUtils.isBlank(metadataNodeParams.getProperties())) {
            metadataNodeParams.setProperties("");
        } else {
            if (MyUtil.checkProperties(metadataNodeParams.getProperties()).isError()) {
                return ApiResult.error("属性格式错误");
            }
        }
        MetadataNode insertMetadataNode = MetadataNode.builder()
                .name(metadataNodeParams.getName())
                .uniqueKey(metadataNodeParams.getUniqueKey())
                .position(metadataNodeParams.getPosition())
                .properties(metadataNodeParams.getProperties())
                .metadataId(metadataNodeParams.getMetadataId())
                .metadataViewId(metadataNodeParams.getMetadataViewId())
                .propertiesKey(ProjectNode.getPropertiesKey(metadataNodeParams.getProperties(), metadataNodeParams.getName()))
                .createdTime(new Date())
                .updatedTime(new Date())
                .build();

        metadataNodeMapper.insertSelective(insertMetadataNode);
        insertMetadataNode.setId(this.metadataNodeMapper.getLastInsertId());

        // 返回-元数据详情
        HashMap<String, Object> map = new HashMap<>();
        map.put("metaDetail", metadataService.getDetailByVewId(insertMetadataNode.getMetadataViewId()).getData());
        map.put("id", "n" + insertMetadataNode.getId());
        map.put("uniqueKey", insertMetadataNode.getUniqueKey());
        map.put("properties", JSON.parseArray(insertMetadataNode.getProperties()));

        // 新增-操作日志
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                .type("MetadataNode.Create")
                .content("创建节点: " + insertMetadataNode.getName())
                .params(insertMetadataNode.getId().toString())
                .createdTime(new Date())
                .build());

        return ApiResult.success(map);
    }

    /**
     * 更新-节点
     *
     * @param metadataNodeParams
     * @return
     */
    public ApiResult update(MetadataNode metadataNodeParams, Integer userId) {
        if (metadataNodeParams.getId() == null) {
            return ApiResult.error("更新节点ID 不能为空");
        }
        MetadataNode node = metadataNodeMapper.selectByPrimaryKey(metadataNodeParams.getId());
        if (node == null) {
            return ApiResult.error("节点不存在");
        }
        if (node.getDataTotal() > 0) {
            return ApiResult.error("节点已被引用，不能修改");
        }
        MetadataNode updateNode = MetadataNode.builder()
                .id(metadataNodeParams.getId())
                .build();
        if (metadataNodeParams.getName() != null) {
            if (StringUtils.isBlank(metadataNodeParams.getName())) {
                return ApiResult.error("节点名称 不能为空");
            }
            if (metadataNodeParams.getName().length() < 2 || metadataNodeParams.getName().length() > 30) {
                return ApiResult.error("节点名称 长度必须在2-30个字符之间");
            }
            updateNode.setName(metadataNodeParams.getName());
            node.setName(metadataNodeParams.getName());
        }
        if (metadataNodeParams.getPosition() != null) {
            try {
                Integer x = JSON.parseObject(metadataNodeParams.getPosition()).getInteger("x");
                Integer y = JSON.parseObject(metadataNodeParams.getPosition()).getInteger("y");
            } catch (Exception e) {
                return ApiResult.error("坐标格式错误");
            }
            updateNode.setPosition(metadataNodeParams.getPosition());
        }
        if (metadataNodeParams.getProperties() != null) {
            updateNode.setProperties(metadataNodeParams.getProperties());
            updateNode.setPropertiesKey(ProjectNode.getPropertiesKey(metadataNodeParams.getProperties(), node.getName()));
        }

        updateNode.setUpdatedTime(new Date());
        metadataNodeMapper.updateByPrimaryKeySelective(updateNode);

        // 新增-操作日志
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                .type("MetadataNode.Update")
                .content("更新节点: " + updateNode.getName())
                .params(updateNode.getId().toString())
                .createdTime(new Date())
                .build());

        // 返回-元数据详情
        return metadataService.getDetailByVewId(node.getMetadataViewId());
    }

    /**
     * 删除节点
     *
     * @param id
     * @param metadataViewId
     * @return
     */
    public ApiResult delete(Integer id, Integer metadataViewId, Integer userId) {
        String username = this.userMapper.selectByPrimaryKey(userId).getUsername();
        MetadataNode metadataNode = metadataNodeMapper.selectOne(
                MetadataNode.builder()
                        .id(id)
                        .metadataViewId(metadataViewId)
                        .build()
        );
        if (metadataNode == null) {
            return ApiResult.error("节点不存在");
        }
        if (metadataNode.getDataTotal() > 0) {
            return ApiResult.error("节点已被引用，不能删除");
        }

        // 删除连线
        metadataEdgeMapper.deleteByNodeId(id);
        List<Integer> edgeIds = metadataEdgeMapper.getIdsByNodeId(id);
        if (edgeIds != null && !edgeIds.isEmpty()) {
            // 记录删除连线操作日志
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(userId)
                    .username(username)
                    .type("MetadataEdge.Delete")
                    .content("删除节点, 联动删除关系: " + edgeIds.size() + " 个")
                    .params(String.join(",", edgeIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
            metadataEdgeMapper.deleteByIdList(edgeIds, metadataViewId);
        }

        // 删除节点
        metadataNodeMapper.deleteByPrimaryKey(id);
        // 新增-操作日志
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(username)
                .type("MetadataNode.Delete")
                .content("删除节点: " + metadataNode.getName())
                .params(id.toString())
                .createdTime(new Date())
                .build());

        // 返回-元数据详情
        return metadataService.getDetailByVewId(metadataNode.getMetadataViewId());
    }

    /**
     * 删除多个节点
     *
     * @param idList
     * @param metadataViewId
     * @return
     */
    public ApiResult deleteAll(List<Integer> idList, Integer metadataViewId, Integer userId) {
        Example example = new Example(MetadataNode.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("id", idList);
        criteria.andEqualTo("metadataViewId", metadataViewId);
        if (this.metadataNodeMapper.selectCountByExample(example) != idList.size()) {
            return ApiResult.error("删除节点-参数错误 1");
        }
        for (Integer id : idList) {
            MetadataNode metadataNode = metadataNodeMapper.selectByPrimaryKey(id);
            if (metadataNode.getDataTotal() > 0) {
                return ApiResult.error("节点已被引用，不能删除");
            }
        }
        this.metadataNodeMapper.deleteByIdList(idList, metadataViewId);

        // 新增-操作日志
        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                .type("MetadataNodeDelete")
                .content("批量删除节点: " + idList.size() + " 个")
                .params(String.join(",", idList.stream().map(String::valueOf).collect(Collectors.toList())))
                .createdTime(new Date())
                .build());

        // 删除连线
        List<Integer> edgeIds = metadataEdgeMapper.getIdsByNodeIds(String.join(",", idList.stream().map(String::valueOf).collect(Collectors.toList())));
        if (edgeIds != null && !edgeIds.isEmpty()) {
            // 记录删除连线操作日志
            this.userOperationLogService.insert(UserOperationLog.builder()
                    .userId(userId)
                    .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                    .type("MetadataEdgeDelete")
                    .content("批量删除节点, 联动删除关系: " + edgeIds.size() + " 个")
                    .params(String.join(",", edgeIds.stream().map(String::valueOf).collect(Collectors.toList())))
                    .createdTime(new Date())
                    .build());
            metadataEdgeMapper.deleteByIdList(edgeIds, metadataViewId);
        }

        // 返回-元数据详情
        return metadataService.getDetailByVewId(metadataViewId);
    }


    public void updateDataTotal(String metadataName,Integer metadataId,Integer dataTotal, Integer userId) {
        this.metadataNodeMapper.updateSetTotalByName(metadataId,metadataName,dataTotal);

        this.userOperationLogService.insert(UserOperationLog.builder()
                .userId(userId)
                .username(this.userMapper.selectByPrimaryKey(userId).getUsername())
                .type("MetadataNode.Update")
                .content("更新节点【"+metadataName+"】数据总数: " + dataTotal + " 个")
                .params(metadataName+"|"+metadataId+"|"+dataTotal)
                .createdTime(new Date())
                .build());
    }

}
